﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.IO;
using MVCScaffold.Extensions;
using System.Data;
using System.Xml.Serialization;
using MVCScaffold.GerenciadoresContexto.Versao1;
using System.Collections;
using System.Collections.Specialized;

namespace MVCScaffold.GerenciadoresContexto
{
    public class GerenciadorEdmx : GerenciadorContexto
    {
        public GerenciadorEdmx(string caminhoEdmx)
        {
            if (String.IsNullOrEmpty(caminhoEdmx))
                throw new ArgumentNullException("Path Edmx.");

            if (!File.Exists(caminhoEdmx))
                throw new FileNotFoundException("EDMX file not found.");


            _entidades = new List<Entity>();
            _propriedadesNavegacao = new NameValueCollection();

            XElement xml = XElement.Load(caminhoEdmx, LoadOptions.SetBaseUri | LoadOptions.SetLineInfo);
            IEnumerable<XElement> enumerable = xml.Elements();

            var xmlSerializer = new XmlSerializer(typeof(TEdmx));
            var edmx = xmlSerializer.Deserialize(new StringReader(xml.ToString())) as TEdmx;

            if (edmx != null)
            {
                CarregarTodasEntitySet(edmx.Items[0] as TRuntime);
            }
        }

        //private void CarregarColumnName(XElement xml)
        //{
        //    List<Property> listaPropriedades = null;
        //    string nome = String.Empty;
        //    List<string> chaves = null;

        //    foreach (var elementos in xml.Elements().Elements().Elements())
        //    {
        //        foreach (var mapeamento in elementos.Elements())
        //        {
        //            foreach (var propriedade in mapeamento.Elements())
        //            {


        //            }
        //        }

        //        if (elementos.Name.LocalName.Equals("EntitySetMapping", StringComparison.OrdinalIgnoreCase))
        //        {

        //        }
        //    }
        //}



        //private void CarregarTodasEntitySet(XElement xml)
        //{
        //    foreach (var item in xml.Elements().Elements())
        //    {
        //        if (item.Name.LocalName.Equals("EntityContainer", StringComparison.OrdinalIgnoreCase))
        //        {
        //            foreach (var entitySet in item.Elements().Where(x => x.Name.LocalName == "EntitySet").Select(x => x.Attribute("Name")))
        //                this.Entidades.Add(new Entity() { Name = entitySet.Value, IsSelected = true });
        //        }
        //    }
        //}

        private void CarregarTodasEntitySet(TRuntime runtime)
        {
            CarregarNamespaceNomeContexto(runtime);


            //var mapping = runtime.Mappings.Mapping.EntityContainerMapping;
            //foreach (var item in mapping.Items)
            //{
            //    if (item is TEntitySetMapping)
            //    {
            //        var novaEntidade = new Entity { IsSelected = true, Properties = new List<Property>() };
            //        var setMapping = item as TEntitySetMapping;
            //        novaEntidade.Name = setMapping.Name;

            //        foreach (var entityTypeMapping in setMapping.Items)
            //        {

            //            if (entityTypeMapping is TEntityTypeMapping)
            //            {
            //                var typeMapping = entityTypeMapping as TEntityTypeMapping;
            //                if (typeMapping.MappingFragment.Count > 0)
            //                {
            //                    foreach (var property in typeMapping.MappingFragment[0].Items)
            //                    {
            //                        if (property is TScalarProperty)
            //                        {
            //                            novaEntidade.Properties.Add(new Property
            //                                                            {
            //                                                                Name = (property as TScalarProperty).Name,
            //                                                                ColumnName = (property as TScalarProperty).ColumnName
            //                                                            });
            //                        }
            //                    }

            //                }
            //            }
            //        }
            //        _entidades.Add(novaEntidade);
            //    }
            //    else
            //    {

            //    }
            //}



            foreach (var entidade in runtime.ConceptualModels.Schema.EntityType)
            {
                var novaEntidade = new Entity() { IsSelected = true, Properties = new List<Property>() };
                foreach (var xmlAttribute in entidade.AnyAttr)
                {
                    if (xmlAttribute.Name.Equals("Name", StringComparison.CurrentCultureIgnoreCase))
                        novaEntidade.Name = xmlAttribute.Value;
                }
                foreach (var item in entidade.Items)
                {

                    if (item is TEntityProperty1)
                    {
                        var propriedade = item as TEntityProperty1;
                        novaEntidade.Properties.Add(new Property
                        {
                            Name = propriedade.Name,
                            Type = Type.GetType(String.Format("System.{0}", propriedade.Type)),
                            IsKey = entidade.Key.Count(x => x.Name == propriedade.Name) > 0,
                        });
                    }
                    else if (item is TNavigationProperty1)
                    {
                        var propriedade = item as TNavigationProperty1;
                        _propriedadesNavegacao.Add(propriedade.Name, propriedade.Relationship);
                    }


                }
                _entidades.Add(novaEntidade);
            }

            DefinePropriedadesNavegacao(runtime.Mappings);
        }

        private void DefinePropriedadesNavegacao(TRuntimeMappings tRuntimeMappings)
        {
            
        }

        private void CarregarNamespaceNomeContexto(TRuntime runtime)
        {
            _namespace = runtime.ConceptualModels.Schema.Namespace;
            if (runtime.ConceptualModels.Schema.EntityContainer != null && runtime.ConceptualModels.Schema.EntityContainer.Count == 1)
                _nomeContext = runtime.ConceptualModels.Schema.EntityContainer[0].Name;
        }


        private void CarregarPropriedade(XElement xml)
        {
            List<Property> listaPropriedades = null;
            string nome = String.Empty;
            List<string> chaves = null;

            foreach (var elementos in xml.Elements().Elements())
            {
                if (elementos.Name.LocalName.Equals("EntityType", StringComparison.OrdinalIgnoreCase))
                {
                    listaPropriedades = new List<Property>();
                    nome = elementos.Attribute("Name").Value;

                    chaves = elementos.Elements()
                        .Where(x => x.Name.LocalName == "Key").Elements()
                        .Select(key => key.Attribute("Name").Value).ToList();

                    foreach (var property in elementos.Elements().Where(x => x.Name.LocalName == "Property"))
                    {
                        var item = new Property()
                                              {
                                                  Name = property.Attribute("Name").Value,
                                                  Type = Type.GetType(String.Format("System.{0}", property.Attribute("Type").Value)),
                                                  IsKey = chaves.Where(x => x == property.Attribute("Name").Value).Count() > 0
                                              };

                        listaPropriedades.Add(item);
                    }

                    var propriedade = Entidades.FirstOrDefault(x => x.Name == nome);
                    propriedade.Properties = listaPropriedades;
                }
            }
        }

        private void VerificarStoreGeneratedPattern(XElement xml)
        {
            List<Property> listaPropriedades = null;
            string nome = String.Empty;
            List<string> chaves = null;

            foreach (var elementos in xml.Elements().Elements())
            {
                if (elementos.Name.LocalName.Equals("EntityType", StringComparison.OrdinalIgnoreCase))
                {
                    listaPropriedades = new List<Property>();
                    nome = elementos.Attribute("Name").Value;

                    chaves = elementos.Elements()
                        .Where(x => x.Name.LocalName == "Key").Elements()
                        .Select(key => key.Attribute("Name").Value).ToList();

                    foreach (var property in elementos.Elements().Where(x => x.Name.LocalName == "Property"))
                    {
                        var item = new Property()
                        {
                            Name = property.Attribute("Name").Value,
                            Type = Type.GetType(String.Format("System.{0}", property.Attribute("Type").Value)),
                            IsKey = chaves.Where(x => x == property.Attribute("Name").Value).Count() > 0
                        };

                        listaPropriedades.Add(item);
                    }

                    var propriedade = Entidades.FirstOrDefault(x => x.Name == nome);
                    propriedade.Properties = listaPropriedades;
                }
            }
        }

        private readonly NameValueCollection _propriedadesNavegacao;

        private string _namespace;
        public override string Namespace
        {
            get { return _namespace; }
        }

        private List<Entity> _entidades;
        public override List<Entity> Entidades
        {
            get { return _entidades; }
        }

        private string _nomeContext;
        public override string NomeContext
        {
            get { return _nomeContext; }
        }
    }
}
